#ifndef _TABLEPLANE_H_
#define _TABLEPLANE_H_

//#define SVD_USING_MAC_ACCELERATE
#define SVD_USING_BOOST_BINDINGS

#include <math.h>

#ifdef SVD_USING_BOOST_BINDINGS
#include <boost/numeric/ublas/matrix_proxy.hpp>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/vector.hpp>
#include <boost/numeric/bindings/traits/ublas_matrix.hpp>
#include <boost/numeric/bindings/traits/ublas_vector.hpp>
#include <boost/numeric/bindings/traits/std_vector.hpp>
#include <boost/numeric/bindings/lapack/gesvd.hpp>
#endif


#ifdef SVD_USING_MAC_ACCELERATE
#include   <Accelerate/Accelerate.h>
#include <clapack.h>
#include <boost/numeric/ublas/matrix.hpp>
#endif

//#include <boost/numeric/ublas/io.hpp>
//#include <boost/numeric/bindings/lapack/geev.hpp>

#include "visgrabTypes.h"
#include "RANSACproblem.h"



class Point3DCol;

class TablePlane : public RANSACproblem< Point3DCol, std::vector<double> > {
 public:
  TablePlane(unsigned int minIter, unsigned int maxIter, double sigma, unsigned int minSamples, bool horizontalAssumption);
  ~TablePlane();

  std::vector<double> getTablePlaneVector();
  std::vector<double> getTablePlaneNormal();
 private:
  int fitPlane(double ** XYZ, int rows,double &pA,double &pB,double &pC,double &pD,double divisionFactor=1.0);
  int planeFitHelp(int &rowsL,int &colsL,int &rows,boost::numeric::ublas::matrix<double> &Mt,double &pA,double &pB,double &pC,double &pD);
  //int fitPlaneMac(double ** XYZ, int rows,double &pA,double &pB,double &pC,double &pD,double divisionFactor=1.0);
  //int planeFitHelpMac(int &rowsL,int &colsL,int &rows, double* Mt,double &pA,double &pB,double &pC,double &pD);

  bool fitModelToData(std::vector<Point3DCol*> &pointCloud);
  double getFitScore();
  void getBestConsensusSet();
  void printBestEstimate();
  //bool fitModelToSampleSet();
  bool _horizontalAssumption;
};

#endif
